#pragma once

#include <Windows.h>
#include <string>
#include <memory>
#include <iostream>
#include <tchar.h>
#include "FileReader.h"


namespace MemoryShared{

#define MEMORY_NAME _T("MemShare")
#define MAX_SIZE_HIGH (0x00000000)
#define MAX_SIZE_LOW (( 1024 * 1024 * 100 ) & 0xFFFFFFFF)



/**
 * @brief 共享内存操作类，用于进程间通过共享内存交换数据
 */
class MemoryMapping {

public:
    /**
     * @brief 构造函数，初始化共享内存指针
     */
    MemoryMapping() : m_buffer(nullptr), m_baseAddress(nullptr) {
    
    }
    
    /**
     * @brief 创建共享内存并映射到当前进程地址空间
     * @note 若创建失败会输出错误信息
     */
    inline void createMemory(){
        do {
            m_memHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAX_SIZE_LOW, MEMORY_NAME);
            if(m_memHandle == nullptr) {
                std::cout<< "CreateFileMapping Failed -> " << GetLastError() << std::endl;
                break;
            }
            m_baseAddress = m_buffer = MapViewOfFile(m_memHandle, FILE_MAP_ALL_ACCESS, 0, 0, MAX_SIZE_LOW);
            if (m_buffer == nullptr) {
                std::cout<< "MapViewOfFile Failed -> " << GetLastError() <<std::endl;
                break;
            }

        }while(0);
        return;
    }
    /**
     * @brief 打开已存在的共享内存并映射到当前进程
     * @return 成功打开返回true，否则返回false
     */
    inline bool openMemory(){
        bool res = true;
        do {
            m_memHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, MEMORY_NAME);
            if(m_memHandle == nullptr) {
                // std::cout<< "OpenFileMappingW Failed -> error code: " << GetLastError() << std::endl;
                res = false;
                break;
            }
            m_baseAddress = m_buffer = MapViewOfFile(m_memHandle, FILE_MAP_ALL_ACCESS, 0, 0, MAX_SIZE_LOW);
            if (m_buffer == nullptr) {
                std::cout<< "MapViewOfFile Failed -> error code: " << GetLastError() << std::endl;
                res = false;
                break;
            }
        }while(0);
        if ( res ) std::cout << "Open Memory success!" << std::endl;
        return res;
    }

    /**
     * @brief 写入数据总大小到共享内存头部
     * @param size 要写入的总数据大小
     */
    inline void writeTotalSize(const size_t& size) {
        if(m_buffer && sizeof(size) <= remainingSize()) {
            memcpy(m_buffer, &size, sizeof(size));
            m_buffer = static_cast<char*>(m_buffer) + sizeof(size);
        }
    }

    /**
     * @brief 从共享内存头部读取总数据大小
     * @return 读取到的总数据大小，失败返回0
     */
    inline size_t readTotalSize() {
        size_t res = 0;
        if(m_buffer && sizeof(size_t) <= remainingSize()) {
            memcpy(&res, m_buffer, sizeof(size_t));
            m_buffer = static_cast<char*>(m_buffer) + sizeof(res);
        }
        return res;
    }

    inline void write(const size_t& data_size, const char*& data) {
        // 写入数据大小
        if (m_buffer && sizeof(size_t) <= remainingSize()) {
            memcpy(m_buffer, &data_size, sizeof(data_size));
            // 使用reinterpret_cast转换为正确类型指针再进行偏移
            m_buffer = static_cast<char*>(m_buffer) + sizeof(data_size);
        }
        // 写入数据内容
        if (m_buffer && data_size <= remainingSize()) {
            memcpy(m_buffer, data, data_size);
            // 使用reinterpret_cast转换为正确类型指针再进行偏移
            m_buffer = static_cast<char*>(m_buffer) + data_size;
        }
    }
    inline void getBuffer(){
        std::cout << "m_buffer -> "<<m_buffer << std::endl;
    }

    inline char* read(const size_t& size) {
        char* res = new char[size];
        if (m_buffer && size <= remainingSize()) {
            // 读取_data_size结构体
            memcpy(res, m_buffer, size);
            m_buffer = static_cast<char*>(m_buffer) + size;
        }
        return res; // 返回默认值
    }

    // 计算剩余可用空间
    inline size_t remainingSize() const {
        if (!m_baseAddress) return 0;
        return MAX_SIZE_LOW - (static_cast<char*>(m_buffer) - static_cast<char*>(m_baseAddress));
    }


    ~MemoryMapping(){
        if (m_buffer) {
            UnmapViewOfFile(m_baseAddress);
            CloseHandle(m_memHandle);
            m_buffer = m_baseAddress = nullptr;
        }
    }


private:
    std::wstring m_sharedMemoryName;
    LPVOID m_buffer;
    LPVOID m_baseAddress; // 保存基地址，用于计算偏移和释放内存
    HANDLE m_memHandle;
};

} // namespace MemoryShared

